﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Simple.Common.Data;
using Simple.Entity;
using Simple.EF;
using Simple.Common.EasyUICommon;
using Simple.ViewModel;
using System.Web.Security;
using System.Web;
using Simple.Common;
using Simple.Common.Core.Encryption;
using Simple.Common.Core.Http;
using Simple.Entity.Models;
using Simple.Service.Enum;
using Simple.Common.Caching;

namespace Simple.Service
{
    public class FormsAuthenticationService : ApplicationService
    {
        private readonly WorkEfRepository<Sys_User> _userRepository;
        private readonly WorkEfRepository<Sys_Menu> _menuRepository;
        private readonly WorkEfRepository<Sys_RoleForMenu> _roleForMenuRepository;
        private readonly WorkEfRepository<Sys_UserForMenu> _userForMenuRepository;
        private readonly WorkEfRepository<Sys_LoginLog> _loginLogRepository;
        private readonly WorkEfRepository<Sys_Role> _sys_RoleRepository;

        private UserPermission _cacheUserPermission;
        private readonly TimeSpan _expirationTimeSpan;

        public FormsAuthenticationService(WorkEfRepository<Sys_User> userRepository, WorkEfRepository<Sys_Menu> menuRepository, WorkEfRepository<Sys_RoleForMenu> roleForMenuRepository, WorkEfRepository<Sys_UserForMenu> userForMenuRepository, WorkEfRepository<Sys_LoginLog> loginLogRepository, WorkEfRepository<Sys_Role> sys_RoleRepository)
        {
            _userRepository = userRepository;
            _menuRepository = menuRepository;
            _roleForMenuRepository = roleForMenuRepository;
            _userForMenuRepository = userForMenuRepository;
            _loginLogRepository = loginLogRepository;
            _sys_RoleRepository = sys_RoleRepository;
            _expirationTimeSpan = FormsAuthentication.Timeout;
        }

        /// <summary>
        /// 验证客户信息
        /// </summary>
        /// <param name="loginNo"></param>
        /// <param name="password"></param>
        /// <param name="sys_User"></param>
        /// <returns></returns>
        public UserLoginResults ValidateCustomer(string loginNo, string password, out Sys_User sys_User)
        {
            sys_User = _userRepository.Table.FirstOrDefault(m => m.LoginNo == loginNo);

            if (sys_User == null)
                return UserLoginResults.CustomerNotExist;
            if (sys_User.IsDeleted)
                return UserLoginResults.Deleted;
            if (!sys_User.IsActive)
                return UserLoginResults.NotActive;

            string pwd = "";
            pwd = SimpleMD5Helper.GetMD5(password + sys_User.PassWordSalt);
            bool isValid = pwd == sys_User.PassWord;
            if (!isValid)
                return UserLoginResults.WrongPassword;

            //save last login date
            sys_User.LastLoginTime = DateTime.Now;
            _userRepository.Update(sys_User);

            _loginLogRepository.Add(new Sys_LoginLog()
            {
                LoginIp = HttpContext.Current.Request.UserHostAddress,
                LoginNo = loginNo,
                LoginTime = DateTime.Now
            });

            return UserLoginResults.Successful;
        }

        /// <summary>
        /// 注册登录，并将用户信息存储起来
        /// </summary>
        /// <param name="Sys_User"></param>
        /// <param name="createPersistentCookie"></param>
        public void SignIn(Sys_User sys_User, bool createPersistentCookie)
        {
            var now = DateTime.UtcNow.ToLocalTime();

            var ticket = new FormsAuthenticationTicket(
               1 /*version*/,
               sys_User.LoginNo,
               now,
               now.Add(_expirationTimeSpan),
               createPersistentCookie,
               sys_User.LoginNo,
               FormsAuthentication.FormsCookiePath);

            var encryptedTicket = FormsAuthentication.Encrypt(ticket);

            var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
            cookie.HttpOnly = true;
            if (ticket.IsPersistent)
            {
                cookie.Expires = ticket.Expiration;
            }
            cookie.Path = FormsAuthentication.FormsCookiePath;
            if (FormsAuthentication.CookieDomain != null)
            {
                cookie.Domain = FormsAuthentication.CookieDomain;
            }

            HttpContext.Current.Response.Cookies.Add(cookie);
            _cacheUserPermission = GetUserPermission(sys_User);
        }

        /// <summary>
        /// 退出
        /// </summary>
        public virtual void SignOut()
        {
            //清空Session退出
            _cacheUserPermission = null;
            SimpleSessionHelper.RemoveAllSession();
            FormsAuthentication.SignOut();
        }

        public UserPermission GetAuthenticatedCustomer()
        {
            if (_cacheUserPermission != null)
                return _cacheUserPermission;
            var formsIdentity = HttpContext.Current.User.Identity;
            if (formsIdentity != null && formsIdentity.IsAuthenticated)
            {
                Sys_User sys_User;
                sys_User = _userRepository.TableNoTracking.FirstOrDefault(m => m.LoginNo == formsIdentity.Name);
                if (sys_User == null || !sys_User.IsActive || sys_User.IsDeleted) return null;
                _cacheUserPermission = GetUserPermission(sys_User);
                return _cacheUserPermission;
            }
            else
            {
                return null;
            }
        }

        private UserPermission GetUserPermission(Sys_User sys_User)
        {
            UserPermission userPermissionDto = new UserPermission();
            userPermissionDto.LoginNo = sys_User.LoginNo;
            userPermissionDto.CustomerName = sys_User.ShortName;
            userPermissionDto.RoleId = sys_User.RoleId.Value;
            userPermissionDto.RoleName = _sys_RoleRepository.TableNoTracking.First(m => m.Id == sys_User.RoleId).RoleName;
            List<Sys_Menu> allMenuInfos = new List<Sys_Menu>();

            var query = from a in _userForMenuRepository.TableNoTracking
                        join b in _menuRepository.TableNoTracking on a.MenuId equals b.Id
                        where a.UserId == sys_User.Id
                        select b;
            allMenuInfos.AddRange(query.ToList());

            query = from a in _roleForMenuRepository.TableNoTracking
                    join b in _menuRepository.TableNoTracking on a.MenuId equals b.Id
                    where a.RoleId == sys_User.RoleId
                    select b;

            allMenuInfos.AddRange(query.ToList());

            if (allMenuInfos != null && allMenuInfos.Count > 0)
            {
                userPermissionDto.MenuList = allMenuInfos.Distinct(new CompareMenuInfo()).OrderBy(m => m.ParentId).ThenBy(m => m.Sort).ToList();
            }
            else
            {
                userPermissionDto.MenuList = allMenuInfos;
            }
            return userPermissionDto;
        }

        private UserPermission GetUserPermission(string loginNo)
        {
            var Sys_User = _userRepository.TableNoTracking.FirstOrDefault(m => m.LoginNo == loginNo);
            if (Sys_User == null) return null;
            return GetUserPermission(Sys_User);
        }

        public SimpleResult ChangePassword(ChangePassWordDto dto)
        {
            var sys_User = _userRepository.Table.FirstOrDefault(m => m.LoginNo == dto.LoginNo);
            sys_User.PassWord = SimpleMD5Helper.GetMD5(dto.NewPassWord + sys_User.PassWordSalt);
            int ret = _userRepository.Update(sys_User);
            return GetResult(ret);
        }
    }

    public class CompareMenuInfo : IEqualityComparer<Sys_Menu>
    {
        public bool Equals(Sys_Menu x, Sys_Menu y)    //比较x和y对象是否相同，按照地址比较
        {
            return x.Id == y.Id;
        }

        public int GetHashCode(Sys_Menu obj)
        {
            return obj.Id.GetHashCode();
        }
    }
}
